using System;
using System.Collections.Generic;

using System.Text;

using Mud.Common.Physical;

using Mud.Common.Messages;
using Mud.Common;

namespace Mud.Server.Physical
{
	/// <summary>
	/// Represents a creature in the game world.
	/// </summary>
    public class Creature : PhysicalObject
    {

        #region Properties

        /// <summary>
        /// This creature brain. Through brain the creature receives commands and perceives events.
        /// </summary>
        public Brain Brain
        {
            get { return _brain; }
            set { _brain = value; }
        }
        private Brain _brain;


        /// <summary>
        /// Command manager for this creature. Holds a list of commands.
        /// </summary>
		public Client.Commands.CommandManager CommandManager
        {
            get { return _commandManager; }
        }
		private Client.Commands.CommandManager _commandManager;

        /// <summary>
        /// Creature sensors, how strongly can it perceive the world.
        /// </summary>
        /// <value></value>
        public Sensors Sensors
        {
            get { return _sensors; }
            set { _sensors = value; }
        }
        private Sensors _sensors;


        #endregion



        /// <summary>
        /// Initializes a new instance of the <see cref="T:Creature"/> class.
        /// </summary>
        /// <param name="server">The server.</param>
		public Creature(IServer server) 
            : base(server) 
        {
			_commandManager = new Client.Commands.CommandManager(this);
            _brain = new Brain(this, new DummyCreatureControler());
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Creature"/> class.
        /// </summary>
        /// <param name="server">The server.</param>
        /// <param name="commandManager">The command manager.</param>
		public Creature(IServer server, Client.Commands.CommandManager commandManager)
            : base(server)
        {
            if (commandManager == null)
                throw new ArgumentNullException("commandManager");

            _commandManager = commandManager;
        }

        public void AttachControler(CreatureControler controler)
        {
            if (controler == null)
                throw new ArgumentNullException("controler");
            controler.ControledCreature = this;
            _brain.CreatureControler = controler;
        }

        #region Checking methods

        /// <summary>
        /// Checks if this creature can see an object.
        /// </summary>
        public ResultWithReason CanView(PhysicalObject o)
        {
            if (Object.ReferenceEquals(o, this))
                return ResultWithReason.Ok;

            int visual = Sensors.VisualSenseStrength;

            return PhysicalUtil.IsInRange(this.Location, o.Location, visual) ? 
                ResultWithReason.Ok : ResultWithReason.Failed("Object is not in visual range.");
        }

        /// <summary>
        /// Checks if this creature can hear something.
        /// </summary>
        public ResultWithReason CanHear(Location origin, CommunicationType type)
        {
            int hearing = Sensors.AcousticSenseStrength;
            switch (type)
            {
                case CommunicationType.VerbalWhisper:
                    hearing /= 2;
                    break;
                case CommunicationType.VerbalYell:
                    hearing *= 2;
                    break;
            }
            return PhysicalUtil.IsInRange(this.Location, origin, hearing) ?
                ResultWithReason.Ok : ResultWithReason.Failed("Object is not in hearing range.");
        }

        public ResultWithReason CanTurn(Orientation orientation)
        {
            return ResultWithReason.Ok;
        }

        public ResultWithReason CanMove(Location target, MovementType type)
        {
            return this.CurrentArea.CanCreatureMove(this, target);

            //switch (this.CurrentArea.Land[target.X, target.Y].Terrain)
            //{
            //    case TerrainType.Water:
            //    case TerrainType.Stone:
            //    case TerrainType.Void:
            //        return ResultWithReason.Failed("You may not move into that terrrain.");

            //    default:
            //        break;
            //}

            //foreach (Creature c in this.CurrentArea.Creatures.Values)
            //{
            //    if (c.Location == target && CanView(c) != ResultWithReason.Ok)
            //        return ResultWithReason.Failed("{0} is standing in your way.", c.Name);
            //}
            //foreach (SimpleObject o in this.CurrentArea.SimpleObjects.Values)
            //{
            //    if (o.Location == target && CanView(o) != ResultWithReason.Ok)
            //        return ResultWithReason.Failed("{0} is standing in your way.", o.Name);
            //}

            //return ResultWithReason.Ok;
        }

        #endregion

    }
}
